//
// Created by admin on 2023/1/30.
//

#include "serial_port.h"
#include "../utils/fd.h"
#include "../utils/error.h"
#include "../utils/log.h"


namespace conn {

using namespace utils;

SerialPort::SerialPort(const char *name, int baud_rate) :
    m_fd(open_port(name))
{
    try {
        set_port_attr(m_fd, baud_rate);
        m_select.set_read_fd(m_fd);
    } catch (const Error &err) {
        close_fd(m_fd);
        throw err;
    }
}

ssize_t SerialPort::read(void *buf, size_t size) {
    return m_select.read(m_fd, buf, size);
}

void SerialPort::write(const void *buf, size_t size) const {
    ssize_t n = ::write(m_fd, buf, size);
    if (n != size) {
        log_e("write fail:%d => %d", size, n);
    }
}

SerialPort::~SerialPort() {
    close_fd(m_fd);
}

void SerialPort::notify_read_exit() {
    m_select.exit_block();
}


uint8_t SerialPort::sync() {
    uint8_t val;
    bool flag = false;
    for (;;) {
        read(&val, 1);

        if ((val != HEAD0) && (val != HEAD1)) {
            log_d("sync:%02x", val);
        }

        if ((val == HEAD1) && flag) {
            break;
        }
        flag = (val == HEAD0);
    }
    read(&val, 1);
    return val;
}

void SerialPort::read_bytes(uint8_t *buf, size_t n) {
    size_t index = 0;
    for (; index < n;) {
        size_t ret = read(buf + index, n - index);
        index += ret;
    }
}


}
